package action

import (
	"database/sql"
	"encoding/json"
	. "etrgo"
	"io"
	"math/rand"
	"strconv"
	"time"
	//"net/http"
	"os"
)

type Product struct {
	ProductId   int
	Name        string
	Catagory    int
	Price       float64
	Description string
	Detail      string
	Priority    int 
	ModifyTime  string
}

type Picture struct {
	ProductId int
	PictureId int
	Seq       int
	Name      string
	Path      string
}

type PictureResult struct {
	Result bool
	Url    string
	Seq    int
	Msg    string
}

func init() {
	rand.Seed(time.Now().Unix())
	//fmt.Println(rand.Int())
	//fmt.Println(rand.Int())
}
func NewProd(action Action) {
	pictures := [...]int{1, 2, 3, 4, 5, 6, 7, 8}
	data := make(map[string]interface{})
	data["pictures"] = pictures
	data["ProductId"] = rand.Int()
	action.Render("prod", data)
}

func getUploadDir() string {
	return Configuration.ImgDir
}

func getUrl() string {
	return Configuration.ImgURL
}

func UploadPicture(action Action) {
	action.Request.ParseMultipartForm(32 << 20)
	f, h, err := action.Request.FormFile("uploadPic")
	if CheckErr(err, "parse the file field of form abortively") {
		return
	}
	filename := h.Filename
	defer f.Close()
	path := getUploadDir() + "/" + filename
	url := getUrl() + "/" + filename
	Debug("upload file[path=%s]", path)
	t, err := os.Create(path)
	if CheckErr(err, "create the picture file abortively") {
		return
	}
	defer t.Close()
	_, err = io.Copy(t, f)

	prodId, err := strconv.ParseInt(action.Request.Form.Get("ProductId"), 10, 32)
	db := GetDB()
	var seq int
	err = db.QueryRow(`select max(seq) from picture where prod_id = ? `, prodId).Scan(&seq)

	if err != nil {
		seq = 1
	} else {
		seq = seq + 1
		//Debug("query err", err)
	}

	stmt, err := GetDB().Prepare(`insert into picture(prod_id,seq,path,pic_name) values(?,?,?,?)`)
	_, err = stmt.Exec(prodId, seq, url, filename)

	if CheckErr(err, "failed to insert picture record.") {
		return
	}
	result := PictureResult{true, url, seq, "upload picture successfully."}
	jsonRes, err := json.Marshal(result)
	if CheckErr(err, "failed to reture the picture url") {
		return
	}
	action.ResponseWriter.Write([]byte(string(jsonRes)))
	//http.Redirect( w,r,"/view?id="+filename,
	//http.StatusFound)
}

func DeletePicture(action Action) {
	action.Request.ParseForm()
	pictureId, _ := strconv.ParseInt(action.Request.Form.Get("PictureId"), 10, 32)
	db := GetDB()
	stmt, err := db.Prepare(`delete from picture where picture_id = ? `)
	_, err = stmt.Exec(pictureId)
	if CheckErr(err, "failed to delete picture["+string(pictureId)+"]") {
		action.ResponseWriter.Write([]byte("Status:-1"))
		return
	}
	action.ResponseWriter.Write([]byte("Status:0"))
}

func EditProdAction(action Action) {
	/*action.Request.ParseForm()
	ParseParams(action.Request, &product)*/

	var product Product
	db := GetDB()
	productId, _ := action.GetInt("ProdId")
	err := db.QueryRow(`select prod_id,prod_name,catalog,price,detail from product where prod_id = ? `, productId).Scan(
		&product.ProductId, &product.Name, &product.Catagory, &product.Price, &product.Detail)
	if err != nil {
		Error("there is no product[productId=%d,err=%s].", productId, err)
	}
	pictures := make([]Picture, 0)
	row, err := db.Query(`select pic_id,seq,pic_name,path from picture where prod_id = ?`, productId)

	var picture Picture
	if err == nil {
		for row.Next() {
			row.Scan(&picture.PictureId, &picture.Seq, &picture.Name, &picture.Path)
			Debug("picture url :%s", picture.Path)
			pictures = append(pictures, picture)
		}
	} else {
		Error("Query picture error[%s].", err)
	}
	if len(pictures) <= 8 {
		picture = Picture{0, 0, 0, "", ""}
		for index := len(pictures); index < 8; index++ {
			picture.Seq = index + 1
			pictures = append(pictures, picture)
		}
	}

	data := make(map[string]interface{})
	data["product"] = product
	data["pictures"] = pictures
	action.Render("prod", data)
	return
}

func SaveProd(action Action) {
	action.Request.ParseForm()
	var product Product
	ParseParams(action.Request, &product)
	db := GetDB()

	err := db.QueryRow(`select 1 from product where id = ? `, product.ProductId).Scan()
	prodExist := false
	var prodDml *sql.Stmt //can't use database.sql.driver
	if err == nil {
		prodExist = true
		prodDml, err = db.Prepare(`update product set prod_name = ? ,catalog = ?,price = ? ,detail = ?,modify_time = current_timestamp
	      where id = ? `)
	} else {
		prodDml, err = db.Prepare(`insert into product(prod_name,catalog,price,detail,create_time,
	     modify_time,status) values(?,?,?,?,current_timestamp,current_timestamp,1)`)
	}
	var productId int64
	if err != nil {
		Error("failed to prepare insert into product.")
		return
	}
	if prodExist {
		_, err = prodDml.Exec(product.Name, product.Catagory, product.Price, product.Description, product.ProductId)
	} else {
		res, err := prodDml.Exec(product.Name, product.Catagory, product.Price, product.Description)
		productId, err = res.LastInsertId()
		if CheckErr(err, "fail to the id of the last inserted product.") {
			return
		}
		updateProdIdSQL, _ := db.Prepare(`update picture set prod_id = ? where prod_id = ? `)
		_, err = updateProdIdSQL.Exec(productId, product.ProductId)
	}

	if err != nil {
		Info("insert into product error.")
		return
	}
	Info("Name=%s,price :%f,desc :%s,catagory:%d", product.Name, product.Price, product.Description, product.Catagory)
	action.Render("prod", nil)
}

func ChgPictureOrder(action Action) {
	action.Request.ParseForm()
	var product Product
	ParseParams(action.Request, &product)
}

func MainAction(action Action) {
	action.Render("main", nil)
}

func SetPriorityAction(action Action){
	productId,_ := action.GetInt("ProdId")
	priority ,_ := action.GetInt("Priority")
	db := GetDB()
	sql,_:= db.Prepare("update product set priority = ? where prod_id = ? ")
	_, err := sql.Exec(priority, productId)
	if err != nil {

	}
}

func ListProdAction(action Action) {
	page := action.GetInt("page")

	db := GetDB()
	queryProdRows, err := db.Query(`select prod_id,prod_name,catalog,price,description,priority,modify_time from product`) //,detail,modify_time

	products := make([]Product, 0)
	if err != nil {
		Error("query error :%s", err)
	}
    mtime := make([] byte, 16)
	for queryProdRows.Next() {
		var product Product
		queryProdRows.Scan(&product.ProductId, &product.Name, &product.Catagory, &product.Price, &product.Description,&product.Priority,&product.ModifyTime)
		Debug("name :%s,%s", product.Name,string(mtime))
		products = append(products, product)
	}
	data := make(map[string]interface{})
	data["products"] = products
	action.Render("listProd", data)
}
